##@package XmlCppClassGenerator.OutputStreams
# Contains a class OutputStream, which allows to define an output
# level above which a message is printed.
#
# @author Johan "Solo" Luisier
# @date November 2011

## Class that implement the "output stream", providing 7 output levels
# : None, Verbose, Debug, Info, Warning, Error and Fatal.
#
# The instance has a tunable reference level: if the wanted output has
# a level greater or equal to the reference, the output is printed. In
# case the wanted output has a too low level, nothing is printed.
#
# The instance also has tunable decorators (i.e. colours for the font
# and the background, attributes) based on ANSI colour codes.
#
# This class was inspired from the MsgStream C++ class used in the
# LHCb experiment. @see
# http://lhcb-release-area.web.cern.ch/LHCb-release-area/DOC/analysis/releases/latest/doxygen/dd/d15/_msg_stream_8h_source.html
#
# @author Johan "Solo" Luisier
# @date November 2011
class OutputStream:
    ## Constructor
    # Initialises the instance, the levels are defined and the current
    # one set to "Info". Decorators are set to some reasonable values.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] level reference level of the current instance.
    def __init__( self, level=3 ) :
        ## Stores the list of existing level names, indexed by the
        # level (number in \f$\left[0,6\right]\f$ interval.
        self.__ListOfLevels = { 0 : "None",
                                1 : "Verbose",
                                2 : "Debug",
                                3 : "Info",
                                4 : "Warning",
                                5 : "Error",
                                6 : "Fatal"
                                }
        ## Stores the list of decorators, which are character strings
        # printed \e before the message, and alters the shell
        # rendering.
        self.__ListOfDecorators = { 0 : "",
                                    1 : "\033[0;32m",
                                    2 : "\033[0;34m",
                                    3 : "",
                                    4 : "\033[0;31m",
                                    5 : "\033[0;37;41m",
                                    6 : "\033[0;37;41;1m"
                                    }
        ## Stores the colour code for each colour, indexed by the
        # colour name. The foreground colour is obtained by adding 30
        # to the number, whilst the backgroundground colour is 40 plus
        # the same number.
        self.__ListOfColours = { "Black"   : 0,
                                 "Red"     : 1,
                                 "Green"   : 2,
                                 "Yellow"  : 3,
                                 "Blue"    : 4,
                                 "Pink"    : 5,
                                 "Cyan"    : 6,
                                 "White"   : 7,
                                 "Default" : 8
                                 }
        # Stores the attribute number indexed by the attribute names.
        self.__ListOfAttributes = { "None"          : 0,
                                    "Bold"          : 1,
                                    "Italic"        : 3,
                                    "Underline"     : 4,
                                    "Blink"         : 6,
                                    "Reverse"       : 7,
                                    "Concealed"     : 8,
                                    "Strikethrough" : 9
                                    }
        if ( level < 0 ) : level = 0
        if ( level > 6 ) : level = 6
        ## Stores the reference output level of the instance
        self.__Level = level
    ## Allows to print the output with the correct decorators.
    # If the wanted output level is greater or equal to the instance
    # reference level, then the string is actually printed to the
    # screen, with the corresponding decorator and the level name
    # appearing at the beginning of the line.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] level wanted output level.
    # @param[in] string what will be printed.
    def doOutput( self, level, string ) :
        if ( level < 0 ) : level = 0
        if ( level > 6 ) : level = 6
        if ( self.__Level <= level ) :
            line = self.__ListOfDecorators[ level ]
            line += "{:<10}".format(self.__ListOfLevels[level])
            line += string
            line += "\033[0;8;8;0m"
            print line
    ## Allows to change the output level of the instance.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] level new value of __Level.
    #
    # @return the value of __Level
    def setOutputLevel( self, level ) :
        self.__Level = level
        return self.__Level
    ## Allows to access the value of __Level.
    #
    # @param[in] self reference on the calling instance.
    #
    # @return the value of __Level
    def getOuputLevel( self ) :
        return self.__Level
    ## Allows to change the decorator for a given output level.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] level level for which the new decorator will be
    # created.
    # @param[in] colourFG foreground colour.
    # @param[in] colourBG background colour.
    # @param[in] attribute attribute (i.e, bold, italic, ...).
    #
    # @return the colour code.
    def setDecorator( self, level, colourFG="Default", colourBG="Default", attribute="None" ) :
        if ( level < 0 ) : level = 0
        if ( level > 6 ) : level = 6
        result = "\033[0;"
        result += str( self.__ListOfColours[ colourFG ] + 30 )
        result += ";"
        result += str( self.__ListOfColours[ colourBG ] + 40 )
        result += ";"
        result += str( self.__ListOfAttributes[ attribute ] )
        result += "m"
        self.__ListOfDecorators[ level ] = result
        return result
    ## Alias to get better access to verbose output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def verbose( self, string ) :
        self.doOutput( 1, string )
    ## Alias to get better access to debug output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def debug( self, string ) :
        self.doOutput( 2, string )
    ## Alias to get better access to info output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def info( self, string ) :
        self.doOutput( 3, string )
    ## Alias to get better access to warning output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def warning( self, string ) :
        self.doOutput( 4, string )
    ## Alias to get better access to error output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def error( self, string ) :
        self.doOutput( 5, string )
    ## Alias to get better access to fatal output.
    #
    # @param[in] self reference on the calling instance.
    # @param[in] string what will be printed.
    def fatal( self, string ) :
        self.doOutput( 6, string )
